查看原文
其他

案例讲解:如何定位容器云平台重大问题

twt社区 twt企业IT社区 2023-01-26
【摘要】在容器平台中,我们除了会涉及操作系统层面的知识,还会涉及容器存储、容器网络、容器日志管理及监控告警、CI/CD(持续集成/持续交付)等相关领域的技术。每个领域都有可能是问题的产生点,只有在分析定位出具体点时,我们才好依据该技术相关工具或者阅读源码来解决它。

【作者】陈强,目前就职于上汽集团云计算中心,容器云架构师及技术经理;长年在云计算领域搬砖,曾就职于Intel, IBM, 爱奇艺等公司;有五年基于Docker/Mesos/Kubernetes的云容器研发经验,积累了丰富的生产实践经验,专注于云原生技术的研究。


定位问题,是在分析问题后,我们可以结合各种日志、监控告警等平台提供的功能来排除干扰项,找到问题的诱发根因。

问题背景:容器平台上线一年多后,总有很少部分租户称他们的某个业务部署在Kubernetes容器平台后经常会重启,也很少部分租户称某个业务在运行一段时间时会产生大量的`CLOSE-WAIT`,还有租户反馈说某个业务跑着就会hang住。刚开始我们都会让业务开发者先自己找问题,因为这些租户反映的只是偶偶发生,大多数租户没有反映类似问题,我们会理所当然的认为是租户业务自身问题,而非平台问题。当然大多数情况下,还是租户业务本身程序没有写好,或者健康检查配置不当等引起。

前文“分析”部分,可点击此处阅读>>>容器云平台重大问题的分析方法

本文继续结合案例讲解如何定位容器云平台重大问题。

1 排除干扰项

分析完了问题,一般会根据经验先从比较简单的可能产生的影响因素开始排除干扰选项,这样我们大概就会有一个比较接近问题根因的方向。

比如上面三个问题中的其中一个 "容器内出现大量处于CLOSE_WAIT状态的TCP链接":

“CLOSE-WAIT”有很多原因引起,有可能是服务端代码处理TCP挥手不合理引起,比如忘记了close相应的socket连接,那么自然不会发出FIN包;还比如出现死循环之类的问题,导致close最后没有被调用执行;还有可能是服务端程序响应过慢,或者存在耗时逻辑,导致close延后;也可能是accept的backlog设置的太大,导致服务端来不及消费的情况,引起多余的请求还在队列里就被对方关闭了。还有可能是内核参数配置没有做优化处理,比如调整“tcp_keepalive_time” / “tcp_keepalive_intvl” / “tcp_keepalive_probes”等。林林总总,但经过我们排查后,以上的可能影响点都不是,所以排除上述这些干扰选项。

在排查业务问题的时候,我们还要结合“业务方”与“平台方”的各自对自身代码熟悉的优势,发挥出凝聚力,一起来排查。

“业务方”——从如下几个方向进行了代码方面的排查:

1、多次检查TCP四次挥手代码逻辑;

2、检查 springboot的相关配置是否恰当;

3、由于连接数过多,也排查了tomcat线程池相关代码;

4、修改ActiveMQ连接池的配置;

5、采用jstack、jmap查看应用的线程堆栈,确定程序没有死锁,只看到少量线程在 block和wait状态;

6、采用jstack-gcutil查看java垃圾回收时间,因为其可能会引起垃圾回收异常等;

以上发现都是正常的,无果。

“平台方”——尝试过以下排查:

1、修改Kubernetes node主机的内核相关配置(比如:tcp keepalived相关参数,ulimit限制数等);

2、检查Kubernetes Ingress入口Nginx的配置(比如:Kubernetes Nginx的超时配置与业务自身Nginx的超时时间减少些,比如900秒;改用NodePort模式不经过Nginx代理等),发现同样有问题,这个就排除采用 Nginx代理引起,也就排除了Nginx参数配置问题;

3、排查docker分区的文件系统,排除容器底层导致;

4、查看dockerd日志和系统日志;

5、还有各种其他可能的方面都尝试过等等;

以上的可能影响点都不是,所以排除上述这些干扰选项。

到此为止,虽然都没有找到一点头绪,但我们至少排除了很多干扰项,这个也是接近根因的必经之路。

当时在分析问题的过程中,实然闪现在我脑海中,会不会是程序本身hang住了,才引起了CLOSE-WAIT出现?这个问题其实是需要界定的,后面会讲到。


2 日志分析

日志平台是日志分析的主要工具,它也是收集业务容器日志及系统日志的输入口,业务日志的展示与统计、分析的窗口。容器的日志都需要统一输出到日志平台,有以下几点考虑:

  • 因为容器的临时性,容器重启或销毁后就会丢失日志,所以需要日志平台的持久存储。

  • 需要按日志存储时间、日志量大小、日志错误类型、业务访问率、客户端访问方式等等来搜索、分析。

  • 需要以图形化展示各种统计效果,方便观察整体表现形为,抓住容易被忽视的抽像部分,也就是有大局观。

2.1 日志平台架构

下面我稍微简要介绍一些日志平台使用到的相关组件的概念,详情请参考相关文献。

早期一般使用ELK架构模式,即由ElasticSearch、Logstash和Kiabana三个开源工具组成:

  • ElasticSearch是一个基于Lucene的开源分布式搜索引擎。它的特点有很多,比如分布式,零配置,自动发现,索引自动分片,索引副本机制,RESTful风格接口,多数据源,自动搜索负载等等。它提供了一个分布式、多用户能力的全文搜索引擎,基于RESTful web接口。ElasticSearch是用Java开发的,并作为Apache许可条款下的开放源码发布。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。在ElasticSearch中,所有节点的数据是均等的。

  • Logstash是一个完全开源的工具,它可以对你的日志进行收集、过滤、分析,支持大量的数据获取方法,并将其存储以实现搜索、统计等功能。它带有一个web界面,可以搜索和展示所有日志。般工作方式为C/S架构,Client端安装在需要收集日志的主机上,Server端负责将收到的各节点日志进行过滤、修改等。

  • Kibana是一个基于浏览器页面的 ElasticSearch前端展示工具,也是一个开源和免费的工具,Kibana可以为Logstash和ElasticSearch提供的日志分析友好的Web界面,可以帮助您汇总、分析和搜索重要数据日志。

最近一般我们采用EFK架构模式,即采用fluentd或者fluent bit来采集容器日志(包括标准控制台日志及用户自定义业务日志)代替Logstash,其他工具保持不变。

Fluentd是一个开源的通用日志采集和分发系统,可以从多个数据源采集日志,并将日志过滤和加工后分发到多种存储和处理系统。Fluentd处于日志采集流程的中间层。它可以从Apache/Nginx等广泛应用的系统、数据库、自定义系统中采集日志,数据进入Fluentd后可根据配置进行过滤、缓存,最终分发到各种后端系统中。这些后端系统包括告警系统(Nagios)、分析系统(MongoDB、MySQL、Hadoop、ElasticSearch)、存储系统(Amazon S3)等。也就是说,Fluentd就是把通常的`日志采集-分发-存储`流程提炼出来,用户只需要考虑业务数据,至于数据的传输、容错等过程细节都交给Fluentd来做。

fluent bit是一个C实现的轻量级多平台开源日志收集工具,相比 fluentd 资源占用要小,相对的插件数量上要比fluentd要少的多,功能上也少一些。它允许从不同的源收集数据并发送到多个目的地。完全兼容Docker和Kubernetes生态环境。

在查询搜索方面,主流的有ElasticSearch,目前也有很多公司开始使用ClickHouse。

ClickHouse是近年来备受关注的开源列式数据库(columnar DBMS),主要用于数据分析(OLAP)领域。目前国内社区火热,各个大厂纷纷跟进大规模使用。传统数据库在数据大小比较小,索引大小适合内存,数据缓存命中率足够高的情形下能正常提供服务。但这种理想情况最终会随着业务的增长而走到尽头,使得查询会变得越来越慢。我们可能会通过增加更多的内存,订购更快的磁盘等纵向扩展的方式来解决问题。如果我们的需求是解决怎样快速查询出结果,那么这就是ClickHouse的主场了。它适用于读多于写;宽表,读大量行但是少量列,结果集较小;数据批量写入,且数据不更新或少更新;无需事务,数据一致性要求低;灵活多变,不适合预先建模等场景。

在我们的生产环境中,一般 7 天内的热日志从ElasticSearch中查询,7 天外的冷日志从ClickHouse中查询,因为随着天数的增加,数据量越来越多,ClickHouse作用越来越明显。携程团队曾对ClickHouse与ElasticSearch做过一次比较,他们得出了如下结论:

  • ClickHouse写入吞吐量大,单服务器日志写入量在50MB到200MB/s,每秒写入超过60W记录数,是ElasticSearch的五倍以上。在ElasticSearch中比较常见的写Rejected导致数据丢失、写入延迟等问题,在ClickHouse中不容易发生。

  • 查询速度快,官方宣称数据在pagecache中,单服务器查询速率大约在2-30GB/s;没在pagecache的情况下,查询速度取决于磁盘的读取速率和数据的压缩率。经测试ClickHouse的查询速度比ElasticSearch快5-30倍以上。

  • ClickHouse比ElasticSearch服务器成本更低。一方面ClickHouse的数据压缩比比ElasticSearch高,相同数据占用的磁盘空间只有ElasticSearch的1/3到1/30,节省了磁盘空间的同时,也能有效的减少磁盘IO,这也是ClickHouse查询效率更高的原因之一;另一方面ClickHouse比ElasticSearch占用更少的内存,消耗更少的CPU资源。我们预估用ClickHouse处理日志可以将服务器成本降低一半。

  • 相比ElasticSearch,ClickHouse稳定性更高,运维成本更低。ElasticSearch中不同的Group负载不均衡,有的Group负载高,会导致写Rejected等问题,需要人工迁移索引;在ClickHouse中通过集群和Shard策略,采用轮询写的方法,可以让数据比较均衡的分布到所有节点。ElasticSearch中一个大查询可能导致OOM的问题;ClickHouse通过预设的查询限制,会查询失败,不影响整体的稳定性。ElasticSearch需要进行冷热数据分离,每天200T的数据搬迁,稍有不慎就会导致搬迁过程发生问题,一旦搬迁失败,热节点可能很快就会被撑爆,导致一大堆人工维护恢复的工作;ClickHouse按天分partition,一般不需要考虑冷热分离,特殊场景用户确实需要冷热分离的,数据量也会小很多,ClickHouse自带的冷热分离机制就可以很好的解决。

  • ClickHouse采用SQL 语法,比ElasticSearch的DSL更加简单,学习成本更低。

2.2 业务日志分析

几乎每个容器平台团队,都会构建自己的日志平台,这样就方便在系统或业务出问题的时候进行排查。一些简单的问题,我们通过业务输出的日志就能够定位到问题,但很多情况下,一些棘手的问题,都需要结合日志统计分析,从全局观入手,还要我们善于观察细节,才好定位出问题点。

我们在定位上述三个问题的时候,也查看了业务日志,但刚开始没有发现什么可疑点,后面我们进行“统计分析”时发现,我们注意到几点:一个非常关键的信息,就是业务的单条日志太长了,目测单行有上万个字符(当然租户日志在生产中输出这么多日志,本身就很不科学,正是这种不科学,才给了我们排查这个问题的机会!)。另外一个就是,1秒钟输出了大量的日志,一条接一条,很快。这两个点,引起了我们的注意。

我们在和业务方排查问题时,我们又注意到一个问题,就是在K8S平台的该业务容器对应的控制台突然看不到业务日志输出了,会不会程序挂了?这个信息很关键,因为这个是一瞬间的事情,由于业务应用设置了健康检查,一旦检查失败超过设定次数,就会自动重启,然后日志重新正常输出,丢失了现场,或者没有注意到这些关键细节就不好排查了。这时执行“ss-ant”查看发现“CLOSE-WAIT”在不断的增加,而此前在日志正常输出时,只会产生少量“CLOSE-WAIT”,所以我断定是业务Hang引起了CLOSE-WAIT的增加。我连续三次敲下统计命令,从图中也可以看出程序挂了后,其CLOSE-WAIT在不断的增加,从166->174->176->178,增长很快。

所以我们让租户把日志输出关闭后,重新压测两天后,并没有产生“CLOSE-WAIT”,到这里我们基本断定了和日志输出有关了。也就是说整个过程是:先有日志过长,导致业务挂死(不过是单条日志过长引起,还是日志输出过快引起,这个需要后面进一步构建模拟代码来判断),最终出现大量CLOSE-WAIT,业务挂了,健康检查失败了,容器自然会重启,突然发现,这三个问题有了关联了!为了证实猜想,我们就需要在之后构建测试程序,来模拟业务程序并复现bug。


3 监控与告警

监控与告警平台是整个容器平台非常重要的辅助功能,它可以帮助我们守护集群健康并及时预警通知,它也是实现自动化运维的必经之路。

3.1 监控告警平台架构

监控告警平台,除了实现传统物理主机层面的监控外,主要会实现容器级别的业务状态、资源使用率等监控。主机层面的监控,可以采用传统的Zabbix进行,比较成熟,这里不做介绍。

容器级别监控的对象主要包括K8S集群(各组件)、应用服务、Pod、容器及网络等。这些对象主要表现为以下三个方面:

  • K8S集群自身健康状态监控(kube-controller-manager/kube-scheduler/kube-apiserver/kubelet/kube-proxy 5个基础组件、Docker、Etcd、网络插件calico,DNS等)

  • 系统性能的监控,比如:cpu、内存、磁盘、网络、filesystem及processes等;

  • 业务资源状态监控,主要包括:rc/rs/deployment/hpa/ds、Pod、Service、Ingress等。

K8S组件相关的监控,早期一般会配合相关的shell脚本,通过crond开启后监控各组件状态,目前可以使用Prometheus来实现系统组件级别的监控。

容器相关的监控,早期采用传统的Heapster+Influxdb+Grafana方案,目前还是Prometheus用的比较多,下面会简要介绍这两种架构方案,具体还请参考相关文献。

3.1.1 Heapster+Influxdb+Grafana方案

监控与告警架构

Cadvisor:将数据,写入InfluxDB

InfluxDB:时序数据库,提供数据的存储,存储在指定的目录下

Grafana:是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括 InfluxDB,MySQL,Elasticsearch,OpenTSDB,Graphite 等)和丰富的插件及模板功能,支持图表权限控制和报警。

Heapster首先从K8S Master获取集群中所有Node的信息,每个Node通过“kubelet”调用“cAdvisor API”来采集所有容器的数据信息(资源使用率和性能特征等)。这样既拿到了Node级别的资源使用状况信息,又拿到了容器级别的信息,它可以通过标签来分组这些信息,之后聚合所有监控数据,一起“sink”到“Heapster”配置的后端存储中(“Influxdb”),通过“Grafana”来支持数据的可视化。所以需要为Heapster设置几个重要的启动参数,一个是“--source”用来指定Master 的 URL作为数据来源,一个是“--sink”用来指定使用的后端存储系统(Influxdb),还有就是“--metric_resolution”来指定性能指标的精度,比如:“30s”表示将过去30秒的数据进行聚合并存储。

这里说一下Heapster的后端存储,它有两个,一个是“metricSink”,另一个是 “influxdbSink”。metricSink是存放在本地内存中的metrics数据池,会默认创建,当集群比较大的时候,内存消耗会很大。Heapster API获取到的数据都是从它那获取的。而influxdbSink接的是我们真正的数据存储后端,在新版本中支持多后端数据存储,比如可以指定多个不同的influxDB 。

通过Grafana,用户可以使用各种正则表达式或者选项查看自己的业务监控详情,还可以按系统性能(cpu、内存、磁盘、网络、filesystem)进行排序查看等等。

监控示例

当监控到一定的数量级,超过某个阈值时,将产生告警。虽然Grafana目前支持邮件进行一些简单的告警,但我们还是通过制定一些监控点、告警机制、告警等级等,然后接入公司内部现有告警平台来进行告警。

邮件告警示例如下:

3.1.2 Promethues方案

Prometheus是一套开源的系统监控和报警框架,灵感源自Google的Borgmon监控系统。2012年,SoundCloud的Google前员工创造了Prometheus,并作为社区开源项目进行开发。2015年,该项目正式发布。2016年,Prometheus加入云原生计算基金会(Cloud Native Computing Foundation),成为受欢迎度仅次于Kubernetes的项目。

Prometheus具有以下特性:

  • 多维的数据模型(基于时间序列的 Key、Value键值对)

  • 灵活的查询和聚合语言PromQL

  • 提供本地存储和分布式存储

  • 通过基于HTTP的Pull模型采集时间序列数据

  • 可利用Pushgateway(Prometheus的可选中间件)实现Push模式

  • 可通过动态服务发现或静态配置发现目标机器

  • 支持多种图表和数据大盘

具体的工作流程如下图所示,数据通过job exporter方式被动收集或者通过Pushgateway主动推送,还可以通过service discovery进行收集到Prometheus server中,Prometheus server会进行加工处理,并将其存储到特有的TSDB数据库,并将数据落盘到主机或者外挂远程持久存储卷中,并以HTTP server方式暴露该服务,Grafana利用Prometheus提供的API接口对接以实现数据的可视化,当监控到异常情况时,可通过AlertManager实现告警,默认的有对接到邮件等,还可以通过Webhook来扩展功能,比如对接到公司已有的告警平台,简单易用。

以上从几个典型的架构上介绍了一些监控,但可能都不是最优实践。这个需要我们根据生产环境的特点结合每个监控产品的优势来达到适合我们监控的目的。比如Grafana的图表展示能力强,但是没有很好的告警功能,那么可以结合Prometheus在数据处理能力改善数据分析的展示。下面列了一些监控产品,但并不是严格按表格进行分类,比如Prometheus和Zabbix都有采集、展示、告警的功能。但都可以了解一下,各取所长。

告警方式有很多,目前主流的是对接到企业微信或者阿里钉钉,方便用手机及时查看。如果要更加智能化处理一些监控告警行为,则可以配合开源的StackStorm来实现自动化运维。

3.2 监控告警分析

监控告警对于我们排查问题其实没有很大的用处,它只能通过监控告诉我们有异常状态发生。但我们可以通过监控告警了解事件发生的具体时间,发生频率,某种情况下,对于长期的很难排查的问题,还是有一定的辅助作用。具体如何分析,这里不做展开,每种监控方式都会有不同的分析方法。

本文是容器云大赛运维管理岗课程之《容器云平台重大问题的分析、定位及排除》中的“定位”部分,您可以点击阅读原文,下载完整课程
觉得本文有用,请转发、点赞或点击“在看”,让更多同行看到


 资料/文章推荐:


欢迎关注社区 "容器云"技术主题 ,将会不断更新优质资料、文章。地址:

https://www.talkwithtrend.com/Topic/98447

■ 本文是社区原创内容,欢迎读者以各种形式转发,网站等平台请勿擅自转载

下载 twt 社区客户端 APP


长按识别二维码即可下载

或到应用商店搜索“twt”


长按二维码关注公众号

*本公众号所发布内容仅代表作者观点,不代表社区立场

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存